<template>
  <div
    :class="{
      'main-form-box': formFontSize === 'default',
      'main-form-box-small': formFontSize === 'small',
      'main-form-box-no-line': !title,
    }"
  >
    <div v-if="title" class="box-title">{{ title }}</div>
    <el-form
      ref="zzFormRef"
      :model="model"
      :rules="rules"
      :label-width="labelWidth + 'px'"
      :label-position="labelPosition"
      :inline="inline"
      :class="{ 'form-readonly': readOnly }"
      @submit.prevent
    >
      <slot></slot>
    </el-form>
  </div>
</template>

<script setup>
import {
  ref,
  watch,
  nextTick,
  onMounted,
  onUpdated,
  onBeforeUnmount,
} from "vue";

// 定义组件名称
defineOptions({
  name: "zzForm",
});

// 定义 props
const props = defineProps({
  model: {
    type: Object,
    default: () => ({}),
  },
  rules: {
    type: Object,
    default: () => ({}),
  },
  title: {
    type: String,
    default: "",
  },
  labelWidth: {
    type: Number,
    default: 80,
  },
  labelPosition: {
    type: String,
    default: "right",
  },
  inline: {
    type: Boolean,
    default: false,
  },
  readOnly: {
    type: Boolean,
    default: false,
  },
  formFontSize: {
    type: String,
    default: "default",
  },
});

// 表单引用
const zzFormRef = ref();

// 获取当前表单的ref
const getZzFormRef = () => {
  return zzFormRef.value;
};

// 表单验证，支持async/await
const validate = async (callback) => {
  const zzForm = getZzFormRef();
  if (zzForm) {
    if (callback && typeof callback === "function") {
      return await zzForm.validate(callback);
    } else {
      return await zzForm.validate();
    }
  }
};

// 表单部分字段校验
const validateField = async (props, callback) => {
  const zzForm = getZzFormRef();
  if (zzForm) {
    return await zzForm.validateField(props, callback);
  }
};

// 表单重置
const resetFields = () => {
  const zzForm = getZzFormRef();
  if (zzForm) {
    zzForm.resetFields();
  }
};

// 清除验证
const clearValidate = (props) => {
  const zzForm = getZzFormRef();
  if (zzForm) {
    zzForm.clearValidate(props);
  }
};

// 监听 readOnly 状态变化
watch(
  () => props.readOnly,
  async (val) => {
    await nextTick();
    setReadonly(!!val);
  },
  { immediate: true }
);

onMounted(async () => {
  await nextTick();
  setReadonly(!!props.readOnly);
});

onUpdated(async () => {
  await nextTick();
  setReadonly(!!props.readOnly);
});

onBeforeUnmount(() => {
  setReadonly(false);
});

// 自动为表单控件设置 readonly/disabled
const setReadonly = (readonly) => {
  const formEl = zzFormRef.value?.$el;
  if (!formEl) return;

  const inputs = formEl.querySelectorAll(
    "input, textarea, select, .el-input__inner"
  );
  inputs.forEach((el) => {
    if (readonly) {
      console.log("设置为 readonly 状态");
      el.setAttribute("readonly", "readonly");
      el.setAttribute("disabled", "disabled");
      if (!el.dataset._placeholder) {
        el.dataset._placeholder = el.placeholder || "";
      }
      el.placeholder = "-";
    } else {
      el.removeAttribute("readonly");
      el.removeAttribute("disabled");

      if (typeof el.dataset._placeholder !== "undefined") {
        el.placeholder = el.dataset._placeholder;
      } else if (el.placeholder === "-") {
        el.placeholder = "";
      }
    }
  });
};

// 暴露方法给父组件
defineExpose({
  getZzFormRef,
  validate,
  validateField,
  resetFields,
  clearValidate,
});
</script>

<style lang="less" scoped>
/* 表单div父级样式 */
.main-form-box {
  position: relative;
  border: 1px solid #ebebf0;
  border-radius: 5px;
  padding: 10px;
  padding-top: 15px;
  transition: box-shadow 0.3s;
  margin-top: 10px;

  /* 表单标题样式 */
  .box-title {
    position: absolute;
    top: -10px;
    padding: 0px 10px;
    font-size: 14px;
    background-color: #fff;
  }

  /* 表单项相关 */
  :deep(.el-form-item) {
    margin-bottom: 15px;
    vertical-align: top;
  }

  /* 日期选择器样式 */
  :deep(.el-date-editor) {
    width: 100%;
  }

  /* 表单验证错误提示样式 */
  :deep(.el-form-item__error) {
    font-size: 10px;
    position: absolute;
    top: 100%;
    left: 10px;
    line-height: 1;
    padding-top: 5px;
    color: #f56c6c;
  }
}

.main-form-box-small {
  position: relative;
  border: 1px solid #ebebf0;
  border-radius: 5px;
  padding: 10px;
  padding-top: 15px;

  /* 表单标题样式 */
  .box-title {
    position: absolute;
    top: -10px;
    padding: 0px 10px;
    font-size: 14px;
    font-weight: bold;
    background-color: #fff;
  }

  /* 表单项相关 */
  :deep(.el-form-item) {
    margin-bottom: 15px;
    vertical-align: top;
  }
  :deep(.el-form-item__label) {
    font-size: 13px;
  }

  /* input相关 */
  /* input主样式 */
  :deep(.el-input__wrapper) {
    padding: 0px 7px;
    height: 30px;
    border-radius: 10px;
  }
  :deep(.el-input__inner) {
    font-size: 13px;
    height: 30px;
    line-height: 30px;
  }

  /* input内图标 */
  :deep(.el-input__suffix) {
    height: 30px;
    line-height: 30px;
  }
  :deep(.el-input__prefix) {
    height: 30px;
    line-height: 30px;
  }

  /* input textarea样式 */
  :deep(.el-textarea__inner) {
    border-radius: 10px;
    font-size: 13px;
  }

  /* 选择框样式 */
  :deep(.el-select .el-input__wrapper) {
    border-radius: 10px;
    font-size: 13px;
    height: 30px;
  }
  :deep(.el-select .el-input__inner) {
    height: 30px;
    line-height: 30px;
    font-size: 13px;
  }

  /* 选择框内默认字体样式 */
  :deep(.el-input__wrapper input::placeholder) {
    font-size: 13px;
  }

  /* 级联选择器字体样式 */
  :deep(.el-cascader .el-input__inner) {
    line-height: 30px;
    font-size: 13px;
  }

  /* 日期选择器样式 */
  :deep(.el-date-editor) {
    width: 100%;
  }
  :deep(.el-date-editor .el-input__wrapper) {
    height: 30px;
  }
  :deep(.el-date-editor .el-input__inner) {
    height: 30px;
    line-height: 30px;
    font-size: 13px;
  }

  /* 单选选择器样式 */
  :deep(.el-radio__label) {
    font-size: 13px;
  }

  /* 复选框样式 */
  :deep(.el-checkbox__label) {
    font-size: 13px;
  }

  /* 上传组件样式 */
  :deep(.el-upload-dragger) {
    border-radius: 17px;
  }
}

/* 表单div父级无标题时样式 */
.main-form-box-no-line {
  border: 0px;
  padding: 0px;
}

/* 鼠标滑过时显示阴影 */
.main-form-box:not(.main-form-box-no-line):hover {
  box-shadow: 0 0 5px rgba(0, 0, 0, 0.3);
}

// readOnly 样式
:deep(.form-readonly) {
  // 通用 input / select / textarea
  .el-input__wrapper,
  .el-select .el-select__wrapper,
  .el-textarea__inner,
  .el-date-editor .el-input__wrapper {
    background-color: transparent !important;
    border: none !important;
    box-shadow: none !important;
    cursor: default !important;
    padding-left: 0 !important;
  }

  // 输入内容字体
  .el-input__inner,
  .el-select .el-select__wrapper,
  .el-textarea__inner {
    color: #000 !important;
    font-weight: 500 !important;
    cursor: default !important;
  }

  // .el-input__inner::placeholder,
  // .el-textarea__inner::placeholder {
  //   color: transparent !important;
  // }

  // 禁用选择器点击
  .el-select,
  .el-date-editor,
  .el-cascader {
    pointer-events: none;
  }

  // 禁止 checkbox / radio 改变状态
  .el-checkbox,
  .el-radio {
    pointer-events: none;
    opacity: 0.7;
  }

  // 上传组件禁用
  .el-upload {
    pointer-events: none;
    opacity: 0.6;
  }
}
</style>
